package org.openmrs.module.simplelabentry.web.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openmrs.Concept;
import org.openmrs.Location;
import org.openmrs.Order;
import org.openmrs.Patient;
import org.openmrs.api.OrderService.ORDER_STATUS;
import org.openmrs.api.context.Context;
import org.openmrs.module.hospitalcore.LabService;
import org.openmrs.module.hospitalcore.model.Lab;
import org.openmrs.module.hospitalcore.model.LabTest;
import org.openmrs.module.simplelabentry.SimpleLabEntryService;
import org.openmrs.web.controller.PortletController;
import org.springframework.util.StringUtils;

public class LabEntryPortletController extends PortletController {

    protected final Log log = LogFactory.getLog(getClass());

    @SuppressWarnings("unchecked")
    protected void populateModel(HttpServletRequest request, Map model) {
    	System.out.println("Entering populateModel [LabEntryPortletController]");
    	log.info("Entering populateModel [LabEntryPortletController]");
        SimpleLabEntryService ls = (SimpleLabEntryService) Context.getService(SimpleLabEntryService.class);
        Lab lab = ls.getCurrentLab();

        // Supported LabTest Sets
        List<Concept> conceptList = new ArrayList<Concept>();
        for (Concept concept : lab.getInvestigationsToDisplay()) {
            if (Context.getUserService().getPrivilege("View " + concept.getName()) != null) {
                for (Concept conceptSetMemeber : ls.getAnswers(concept)) {
                    conceptList.add(conceptSetMemeber);
                }
            }
        }
        model.put("labTestConcepts", conceptList);
        model.put("confidentialTestConcepts", lab.getConfidentialTestsToDisplay());
        model.put("patientIdType", lab.getPatientIdentifierType().getPatientIdentifierTypeId());
        // Retrieve Orders that Match Input Parameters
        String identifier = "";
        String orderLocationId = (String) model.get("orderLocation");
        String orderSetConceptId = (String) model.get("orderConcept");
        String groupKey = request.getParameter("groupKey");
        String orderDateStr = request.getParameter("orderDate");
        Calendar cal = Calendar.getInstance();
        Date today = cal.getTime();
//        log.info("orderDateStr = " + orderDateStr);
        Date orderDate1;
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        model.put("today", sdf.format(today));
        if (orderDateStr == null || orderDateStr.equals("")) {
            if (model.get("confidentialTest").equals("true")) {
                orderDateStr = sdf.format(today);
//                log.info("_________________________________orderDate = " + today + " orderDateStr = " + orderDateStr);
                model.put("orderDateStr", orderDateStr);
            }
        } else {
            try {
                orderDate1 = sdf.parse(orderDateStr);
                if (orderDate1.after(today)) {
                    model.put("futureDate", "true");
                } else {
                    System.out.println("putting in model futuredate = false");
                    model.put("futureDate", "false");
                }
            } catch (ParseException ex) {
                Logger.getLogger(LabEntryPortletController.class.getName()).log(Level.SEVERE, null, ex);
            }
            model.put("orderDateStr", orderDateStr);
        }

        if (request.getParameter("identifier") != null) {
            identifier = request.getParameter("identifier");
        } else {
            identifier = (String) model.get("identifier");
        }
        if( identifier != null ){
       	 String prefix = Context.getAdministrationService().getGlobalProperty("registration.identifier_prefix");
            if( identifier.contains("-") && !identifier.contains(prefix)){
            	identifier = prefix+identifier;
        	}
       }
        if (groupKey != null && !groupKey.equalsIgnoreCase("Select")) {
            orderSetConceptId = Context.getConceptService().getConcept(request.getParameter("groupKey")).getId().toString();
        } else if (request.getParameter("labName") != null) {
            if (request.getParameter("labName").equals("Select")) {
                orderSetConceptId = "Select";
            } else {
                orderSetConceptId = Context.getConceptService().getConcept(request.getParameter("labName")).getId().toString();
            }
        }
        // log.info("orderSetConceptId = " + orderSetConceptId);
        /*if(!orderSetConceptId.equals("Select"))
        model.put("orderConcept", Context.getConceptService().getConcept(orderSetConceptId));*/
        //orderSetConcept = request.getParameter("groupKey");
        model.put("groupConceptId", orderSetConceptId);
        String limit = (String) model.get("limit");
        // Retrieve global properties
        model.put("orderTypeId", lab.getLabOrderType().getId());
        log.info("Retrieving orders for: location=" + orderLocationId + ",concept=" + orderSetConceptId + "," + "date=" + orderDateStr + ",identifier=" + identifier + ",limit=" + limit);

        Map<String, Concept> orderConceptMap = new HashMap<String, Concept>();
        model.put("patientIdentifierType", lab.getPatientIdentifierType().getId());
        List<Order> labOrderList = new ArrayList<Order>();
        LabService labService = Context.getService(LabService.class);
        Map<Integer, String> mapLabTest = new HashMap<Integer, String>();
        try {
            Concept concept = null;

            if (orderSetConceptId != null) {
                if (!orderSetConceptId.equalsIgnoreCase("Select")) {
                    concept = StringUtils.hasText(orderSetConceptId) ? Context.getConceptService().getConcept(Integer.parseInt(orderSetConceptId)) : null;
                }
            }

            Location location = StringUtils.hasText(orderLocationId) ? Context.getLocationService().getLocation(Integer.parseInt(orderLocationId)) : null;
            Date orderDate = StringUtils.hasText(orderDateStr) ? Context.getDateFormat().parse(orderDateStr) : null;
            ORDER_STATUS status = "open".equals(limit) ? ORDER_STATUS.CURRENT : "closed".equals(limit) ? ORDER_STATUS.COMPLETE : ORDER_STATUS.NOTVOIDED;
            List<Patient> patients = null;
            List<Concept> allTestsList = new ArrayList<Concept>();
            boolean check = true;
           
            System.out.println("ID : "+identifier);
            if (StringUtils.hasText(identifier)) {
                patients = Context.getPatientService().getPatients(identifier);
                if (patients.isEmpty()) {
                    check = false;
                }
                log.info("Found: " + patients + " for identifier=" + identifier);
            }
            if (check) {

                // Retrieve matching orders
                List<Concept> conceptLists = new ArrayList<Concept>();
                if (concept == null) {
                    if (orderSetConceptId != null) {
                        System.out.println("orderSetConceptId = " + orderSetConceptId);
                        if (orderSetConceptId.equals("Select")) {
                            for (Concept concept1 : ls.getSupportedLabConcepts()) {
                                //log.info("concept1 = " + concept1.getName());

                                if (Context.getUserService().getPrivilege("View " + concept1.getName()) != null) {
                                    System.out.println(" concept = "+concept1.getName());
                                    conceptLists.add(concept1);
                                }
                            }
                        }
                    }
                }
                if (patients != null || location != null || orderDate != null) {
                    if (groupKey != null && !groupKey.equalsIgnoreCase("Select")) {
                        if (concept != null) {
                            List<Order> orderList = ls.getLabOrders(concept, location, orderDate, status, patients, lab.getInvestigationsToDisplay(), lab.getLabOrderType());
                            LabTest labTest = null;
                            for (Order order : orderList) {
                                labOrderList.add(order);
                                labTest = labService.getLabTestByOrder(order);
                                if( labTest != null )
                                	mapLabTest.put(order.getOrderId(), labTest.getSampleNumber());
                                
                            }
                            log.info("Found: total " + labOrderList.size() + " LabOrders  and found " + orderList.size() + " laborders for test " + concept);
                        }
                    } else if (request.getParameter("labName") != null) {
                        System.out.println("inside labname = "+request.getParameter("labName"));
                        if (concept != null) {
                            //System.out.println("concept is not null");
                            for (Concept conceptSetMemeber : ls.getAnswers(concept)) {
                                allTestsList.add(conceptSetMemeber);
                            }
                            log.debug("Found: total " + allTestsList.size() + " Tests for test " + concept);
                        } else {
                            System.out.println("concept is null");
                            if (!conceptLists.isEmpty()) {
                                for (Concept concept1 : conceptLists) {
                                    for (Concept conceptSetMemeber : ls.getAnswers(concept1)) {
                                        allTestsList.add(conceptSetMemeber);
                                    }
                                    log.debug("Found: total " + allTestsList.size() + " Tests for test " + concept1);
                                }
                            }
                        }
                        for (Concept testName : allTestsList) {
                            List<Order> orderList = ls.getLabOrders(testName, location, orderDate, status, patients, lab.getInvestigationsToDisplay(), lab.getLabOrderType());
                            LabTest labTest = null;
                            for (Order order : orderList) {
                                labOrderList.add(order);
                                labTest = labService.getLabTestByOrder(order);
                                if( labTest != null )
                                	mapLabTest.put(order.getOrderId(), labTest.getSampleNumber());
                                
                            }
                            log.debug("Found: total " + labOrderList.size() + " LabOrders  and found " + orderList.size() + " laborders for test " + testName);
                        }
                    }
                }
            }
            if (!labOrderList.isEmpty()) {
                Collections.sort(labOrderList, new Comparator<Order>() {

                    public int compare(Order o1, Order o2) {
                        return o1.getStartDate().compareTo(o2.getStartDate());
                    }
                });
            }
            //System.out.println("worklist = "+model.get("workList"));
            if (model.get("workList") != null && model.get("workList").equals("true")) {
            	List<Order> workList = new ArrayList<Order>();
            	List<LabTest> listLabTest = labService.getLatestLabTestByDate(ls.getCurrentLab(),orderDate );
                for (LabTest test : listLabTest) {
                    workList.add(test.getOrder());
                }
                model.put("labOrders", workList);
            } else {
                model.put("labOrders", labOrderList);
            }
            model.put("mapLabTest",mapLabTest);
            
        } catch (Exception e) {
            throw new RuntimeException("Server Error: Unable to load order list.", e);
        }
       
    }
}
